import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';

import { Select, Spin, TreeSelect } from 'antd';
import { debounce } from 'lodash-es';

// 组件 Props 类型定义
interface RemoteSelectProps {
	// 基础属性
	value?: any;
	onChange?: (value: any, option?: any) => void;
	onSelect?: (value: any, option?: any) => void;
	placeholder?: string;
	disabled?: boolean;
	allowClear?: boolean;
	searchParams?: Record<string, any>;

	// 选择模式
	mode?: 'single' | 'multiple';

	// 组件类型
	type?: 'select' | 'treeSelect';

	// 远程请求相关
	fetchData: (params: FetchParams) => Promise<FetchResponse>;
	transformData?: (data: any[]) => OptionItem[];

	// 搜索和分页
	searchable?: boolean;
	pageSize?: number;
	debounceWait?: number;

	// 样式
	style?: React.CSSProperties;
	className?: string;

	// TreeSelect 特有属性
	treeCheckable?: boolean;
	treeDefaultExpandAll?: boolean;
	treeNodeFilterProp?: string;
}

// 请求参数类型
export interface FetchParams {
	keyword?: string;
	page: number;
	pageSize: number;
	[propName: string]: unknown;
}

// 请求响应类型
interface FetchResponse {
	data: unknown[];
	total: number;
	hasMore?: boolean;
}

// 选项数据类型
interface OptionItem {
	label: string;
	value: any;
	disabled?: boolean;
	children?: OptionItem[];
	// TreeSelect 特有
	title?: string;
	key?: string;
}

const RemoteSelect: React.FC<RemoteSelectProps> = ({
	value,
	onChange,
	onSelect,
	placeholder = '请选择',
	disabled = false,
	allowClear = true,
	mode = 'single',
	type = 'select',
	fetchData,
	transformData,
	searchable = false,
	pageSize = 30,
	debounceWait = 300,
	style,
	className,
	treeCheckable = false,
	treeDefaultExpandAll = false,
	treeNodeFilterProp = 'title',
	searchParams = {}
}) => {
	// 状态管理
	const [options, setOptions] = useState<OptionItem[]>([]);
	const [loading, setLoading] = useState(false);
	const [searchValue, setSearchValue] = useState('');
	const [currentPage, setCurrentPage] = useState(1);
	const [hasMore, setHasMore] = useState(true);
	const [total, setTotal] = useState(0);
	const [oldSearchParams, setOldSearchParams] = useState<Record<string, any>>();

	// refs
	const selectRef = useRef<any>(null);
	const fetchingRef = useRef(false);

	// 默认数据转换函数
	const defaultTransformData = useCallback((data: any[]): OptionItem[] => {
		return data.map(item => ({
			label: item.label ?? item.name ?? item.title ?? String(item.value),
			value: String(item.value ?? item.id),
			disabled: item.disabled ?? false,
			children: item.children ? defaultTransformData(item.children) : undefined,
			// TreeSelect 特有属性
			title: item.title ?? item.label ?? item.name ?? String(item.value),
			key: String(item.value ?? item.id)
		}));
	}, []);

	// 获取数据
	const loadData = useCallback(
		async (keyword: string = '', page: number = 1, append: boolean = false) => {
			if (fetchingRef.current) return;

			fetchingRef.current = true;
			setLoading(true);
			try {
				const response = await fetchData({
					...searchParams,
					keyword,
					page,
					pageSize
				});

				const transformedData = transformData
					? transformData(response.data)
					: defaultTransformData(response.data);

				setOptions(prev => (append ? [...prev, ...transformedData] : transformedData));
				setTotal(response.total);
				setHasMore(response.hasMore ?? response.data.length === pageSize);
				setCurrentPage(page);
			} catch (error) {
				console.error('Failed to fetch data:', error);
			} finally {
				setLoading(false);
				fetchingRef.current = false;
			}
		},
		[fetchData, transformData, defaultTransformData, pageSize, searchParams]
	);

	// 防抖搜索
	const debouncedSearch = useMemo(
		() =>
			debounce((keyword: string) => {
				setSearchValue(keyword);
				setCurrentPage(1);
				loadData(keyword, 1, false);
			}, debounceWait),
		[loadData, debounceWait]
	);

	// 初始化加载数据
	useEffect(() => {
		if (JSON.stringify(oldSearchParams) !== JSON.stringify(searchParams)) {
			console.log('初始化加载数据', searchParams);
			setOldSearchParams(searchParams);
			loadData();
		}
	}, [searchParams]);

	// 搜索处理
	const handleSearch = useCallback(
		(keyword: string) => {
			if (searchable) {
				debouncedSearch(keyword);
			}
		},
		[searchable, debouncedSearch]
	);

	// 滚动加载更多
	const handlePopupScroll = useCallback(
		(e: React.UIEvent<HTMLDivElement>) => {
			const { target } = e;
			const element = target as HTMLDivElement;

			if (
				element.scrollTop + element.offsetHeight === element.scrollHeight &&
				hasMore &&
				!loading &&
				!fetchingRef.current
			) {
				loadData(searchValue, currentPage + 1, true);
			}
		},
		[hasMore, loading, searchValue, currentPage, loadData]
	);

	// 值变化处理
	const handleChange = useCallback(
		(val: any, option: any) => {
			onChange?.(val, option);
			onSelect?.(val, option);
		},
		[onChange, onSelect]
	);

	// 清空搜索
	const handleClear = useCallback(() => {
		setSearchValue('');
		setCurrentPage(1);
		loadData('', 1, false);
	}, [loadData]);

	// Select 组件配置
	const selectProps = {
		value,
		onChange: handleChange,
		placeholder,
		disabled,
		allowClear,
		style,
		className,
		ref: selectRef,
		loading,
		options,
		showSearch: searchable,
		onSearch: handleSearch,
		onClear: handleClear,
		onPopupScroll: handlePopupScroll,
		filterOption: false, // 关闭本地过滤，使用远程搜索
		notFoundContent: loading ? <Spin size="small" /> : '暂无数据',
		popupRender: (menu: React.ReactNode) => (
			<div>
				{menu}
				{loading && hasMore && (
					<div style={{ textAlign: 'center', padding: '8px' }}>
						<Spin size="small" />
					</div>
				)}
			</div>
		)
	};

	// TreeSelect 组件配置
	const treeSelectProps = {
		...selectProps,
		treeData: options,
		treeCheckable: mode === 'multiple' ? treeCheckable : false,
		treeDefaultExpandAll,
		treeNodeFilterProp,
		showCheckedStrategy: TreeSelect.SHOW_PARENT
	};

	// 根据模式设置选择属性
	if (mode === 'multiple') {
		selectProps.mode = 'multiple';
		if (type === 'treeSelect') {
			treeSelectProps.multiple = true;
		}
	}
	// console.log('treeSelectProps', treeSelectProps);

	// 渲染组件
	if (type === 'treeSelect') {
		return <TreeSelect {...treeSelectProps} />;
	}

	return <Select {...selectProps} />;
};

export default RemoteSelect;

export const RemoteSelectExample: React.FC = () => {
	const [value, setValue] = useState<any>();
	const [multiValue, setMultiValue] = useState<any[]>([]);
	const [treeValue, setTreeValue] = useState<any>();

	// 模拟远程数据获取
	const mockFetchData = async ({
		keyword,
		page,
		pageSize
	}: FetchParams): Promise<FetchResponse> => {
		// 模拟网络延迟
		await new Promise(resolve => setTimeout(resolve, 500));

		// 模拟数据
		const allData = Array.from({ length: 100 }, (_, i) => ({
			id: i + 1,
			name: `选项 ${i + 1} ${keyword ? `(搜索: ${keyword})` : ''}`,
			value: i + 1,
			disabled: i % 10 === 0 // 每10个有一个禁用
		}));

		// 模拟搜索过滤
		const filteredData = keyword
			? allData.filter(item => item.name.toLowerCase().includes(keyword.toLowerCase()))
			: allData;

		// 分页
		const start = (page - 1) * pageSize;
		const end = start + pageSize;
		const pageData = filteredData.slice(start, end);

		return {
			data: pageData,
			total: filteredData.length,
			hasMore: end < filteredData.length
		};
	};

	// 模拟树形数据获取
	const mockFetchTreeData = async ({
		keyword,
		page,
		pageSize
	}: FetchParams): Promise<FetchResponse> => {
		await new Promise(resolve => setTimeout(resolve, 500));

		const treeData = Array.from({ length: 50 }, (_, i) => ({
			id: i + 1,
			title: `父节点 ${i + 1}`,
			value: `parent-${i + 1}`,
			children: Array.from({ length: 3 }, (__, j) => ({
				id: `${i + 1}-${j + 1}`,
				title: `子节点 ${i + 1}-${j + 1}`,
				value: `child-${i + 1}-${j + 1}`
			}))
		}));

		const filteredData = keyword
			? treeData.filter(
					item =>
						item.title.toLowerCase().includes(keyword.toLowerCase()) ||
						item.children.some(child => child.title.toLowerCase().includes(keyword.toLowerCase()))
				)
			: treeData;

		const start = (page - 1) * pageSize;
		const end = start + pageSize;
		const pageData = filteredData.slice(start, end);

		return {
			data: pageData,
			total: filteredData.length,
			hasMore: end < filteredData.length
		};
	};

	return (
		<div style={{ padding: '24px' }}>
			<h2>RemoteSelect 组件示例</h2>

			<div style={{ marginBottom: '24px' }}>
				<h3>单选 Select</h3>
				<RemoteSelect
					value={value}
					onChange={setValue}
					fetchData={mockFetchData}
					placeholder="请选择单个选项"
					style={{ width: '300px' }}
				/>
				<p>选中值: {JSON.stringify(value)}</p>
			</div>

			<div style={{ marginBottom: '24px' }}>
				<h3>多选 Select</h3>
				<RemoteSelect
					mode="multiple"
					value={multiValue}
					onChange={setMultiValue}
					fetchData={mockFetchData}
					placeholder="请选择多个选项"
					style={{ width: '300px' }}
				/>
				<p>选中值: {JSON.stringify(multiValue)}</p>
			</div>

			<div style={{ marginBottom: '24px' }}>
				<h3>TreeSelect</h3>
				<RemoteSelect
					type="treeSelect"
					value={treeValue}
					onChange={setTreeValue}
					fetchData={mockFetchTreeData}
					placeholder="请选择树形选项"
					style={{ width: '300px' }}
					treeCheckable={false}
					treeDefaultExpandAll={true}
				/>
				<p>选中值: {JSON.stringify(treeValue)}</p>
			</div>
		</div>
	);
};
